﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;
using Newtonsoft.Json;
using War3Trainer.WindowsApi;
using static System.Runtime.CompilerServices.RuntimeHelpers;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.Header;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.Window;

namespace War3Trainer
{
    public partial class MainForm : Form
    {
        // Token: 0x04000001 RID: 1
        public static string UserModifyKeyCode = "F2";

        // Token: 0x04000002 RID: 2
        public static string ResourceModifyKeyCode = "F3";

        // 全局变量（定义在类中）
        private readonly Dictionary<string, DateTime> _lastUpdateTimes = new Dictionary<string, DateTime>();
        private readonly object _lockObj = new object(); // 多线程安全

        private GameContext _currentGameContext;
        private GameTrainer _mainTrainer;
        private NetworkManager _networkManager;

        private KeyboardHook hook;
        private SelectedNodeAllAttr selectedAllNode = new SelectedNodeAllAttr();
        public static TreeNode selected;

        public MainForm()
        {
            InitializeComponent();
            SetRightGrid(RightFunction.Introduction);
            // Initialize network manager
            _networkManager = new NetworkManager(OnUpdateReceived);
            _networkManager.Start();
            StartTimer();
        }

        private System.Threading.Timer timer;

        private void StartTimer()
        {
            timer = new System.Threading.Timer(_ =>
            {
                // 在线程池中，更新UI前调用Invoke
                if (dataNetClients.InvokeRequired)
                {
                    dataNetClients.Invoke(new MethodInvoker(UpdateData));
                }
                else
                {
                    UpdateData();
                }
            }, null, 0, 3000); // 初始延迟0，间隔3000毫秒
        }

        // 存储本次数据
        private Dictionary<string, string> previousData = new Dictionary<string, string>();


        private void UpdateData()
        {
            var currentData = new Dictionary<string, string>();
            var rowsToRemove = new List<DataGridViewRow>();
            // 构建当前数据字典
            foreach (var key in _networkManager.SHARE_DATA.Keys)
            {
                var parts = key.Split(':');
                if (parts.Length < 2)
                    continue;

                var valuesList = _networkManager.SHARE_DATA[key];
                string valuesString = string.Join(",", valuesList);
                string rowKey = $"{parts[0]}|{parts[1]}";

                currentData[rowKey] = valuesString;
            }

            // 1. 更新或添加新行，或者标记删除
            foreach (var kvp in currentData)
            {
                var rowKey = kvp.Key;
                var newValue = kvp.Value;

                // 查找对应行
                var row = dataNetClients.Rows.Cast<DataGridViewRow>()
                    .FirstOrDefault(r => r.Cells[0].Value?.ToString() + "|" + r.Cells[1].Value?.ToString() == rowKey);

                if (row != null)
                {
                    // 存在此行，检查是否值变化
                    if (row.Cells[2].Value?.ToString() != newValue)
                    {
                        row.Cells[2].Value = newValue; // 只更新变化部分
                    }
                }
                else
                {
                    // 新增行
                    var parts = rowKey.Split('|');
                    dataNetClients.Rows.Add(parts[0], parts[1], newValue);
                }
            }

            // 2. 找出需要删除的行（在旧缓存中但不在当前数据中）
            foreach (DataGridViewRow row in dataNetClients.Rows)
            {
                if (row.IsNewRow) continue; // 跳过新行模板
                var key = row.Cells[0].Value?.ToString() + "|" + row.Cells[1].Value?.ToString();
                if (!currentData.ContainsKey(key))
                {
                    // 标记为待删除的行
                    rowsToRemove.Add(row);
                }
            }

            // 3. 移除已不存在的数据行
            foreach (var row in rowsToRemove)
            {
                dataNetClients.Rows.Remove(row);
            }

            // 4. 更新缓存
            previousData = new Dictionary<string, string>(currentData);

        }

        private void FrmMain_Load(object sender, EventArgs e)
        {
            try
            {

                System.Diagnostics.Process.EnterDebugMode();
            }
            catch
            {
                ReportEnterDebugFailure();
                return;
            }

            FindGame();

            btnEnableKeyListener_Click(sender, e);
        }

        private void OnUpdateReceived(string updateMessage)
        {
            // This will be called when an update is received from another machine
            if (InvokeRequired)
            {
                Invoke(new Action<string>(OnUpdateReceived), updateMessage);
                return;
            }

            // Parse and apply the update
            ApplyNetworkUpdate(updateMessage);
        }

        /************************************************************************/
        /* Main functions                                                       */
        /************************************************************************/
        private void FindGame()
        {
            bool isRecognized = false;
            try
            {
                _currentGameContext = GameContext.FindGameRunning("war3", "game.dll");
                if (_currentGameContext == null)
                {
                    // netease war3 platform(dz.163.com)
                    _currentGameContext = GameContext.FindGameRunning("War3Loader", "game.dll");
                }
                if (_currentGameContext != null)
                {
                    // Game online
                    ReportVersionOk(_currentGameContext.ProcessId, _currentGameContext.ProcessVersion);

                    // Get a new trainer
                    GetAllObject();

                    isRecognized = true;
                }
                else
                {
                    // Game offline
                    ReportNoGameFoundFailure();
                }
            }
            catch (UnkonwnGameVersionExpection ex)
            {
                // Unknown game version
                _currentGameContext = null;
                ReportVersionFailure(ex.ProcessId, ex.GameVersion);
            }
            catch (WindowsApi.BadProcessIdException ex)
            {
                this._currentGameContext = null;
                ReportProcessIdFailure(ex.ProcessId);
            }
            catch (Exception ex)
            {
                // Why here?
                _currentGameContext = null;
                ReportUnknownFailure(ex.Message);
            }

            // Enable buttons
            if (isRecognized)
            {
                viewFunctions.Enabled = true;
                viewData.Enabled = true;
                cmdGetAllObjects.Enabled = true;
                cmdModify.Enabled = true;
            }
            else
            {
                viewFunctions.Enabled = false;
                viewData.Enabled = false;
                cmdGetAllObjects.Enabled = false;
                cmdModify.Enabled = false;
            }
        }

        private void GetAllObject(String index = "1", bool syncSelected = false)
        {
            // Check paramters
            if (_currentGameContext == null)
                return;

            // Get a new trainer
            _mainTrainer = new GameTrainer(_currentGameContext);

            // Create function tree
            viewFunctions.Nodes.Clear();
            foreach (ITrainerNode currentFunction in _mainTrainer.GetFunctionList())
            {
                TreeNode[] parentNodes = viewFunctions.Nodes.Find(currentFunction.ParentIndex.ToString(), true);
                TreeNodeCollection parentTree;
                if (parentNodes.Length < 1)
                    parentTree = viewFunctions.Nodes;
                else
                    parentTree = parentNodes[0].Nodes;

                parentTree.Add(
                    currentFunction.NodeIndex.ToString(),
                    currentFunction.NodeTypeName)
                    .Tag = currentFunction;
            }
            viewFunctions.ExpandAll();

            // Switch to page 1
            TreeNode[] introductionNodes = viewFunctions.Nodes.Find(index, true);
            if (introductionNodes.Length > 0)
            {
                viewFunctions.SelectedNode = introductionNodes[0];
                if (viewFunctions.SelectedNode.Text.StartsWith("0x"))
                {
                    // 当前选中
                    selected = viewFunctions.SelectedNode;
                    if (syncSelected)
                    {
                        _networkManager.SendBroadcastsWithSelected();
                    }
                }
                SelectFunction(introductionNodes[0]);
            }
        }

        // Re-query specific tree-node by FunctionListNode
        private void RefreshSelectedObject(ITrainerNode currentFunction)
        {
            TreeNode[] currentNodes = viewFunctions.Nodes.Find(currentFunction.NodeIndex.ToString(), true);
            TreeNode currentTree;
            if (currentNodes.Length < 1)
                return;
            else
                currentTree = currentNodes[0];

            currentTree.Text = currentFunction.NodeTypeName;
        }

        private void SelectFunction(TreeNode functionNode)
        {
            if (functionNode == null)
                return;
            ITrainerNode node = functionNode.Tag as ITrainerNode;
            if (node == null)
                return;

            // Show introduction page
            if (node.NodeType == TrainerNodeType.Introduction)
            {
                SetRightGrid(RightFunction.Introduction);
            }
            else
            {
                // Fill address list
                FillAddressList(node.NodeIndex);

                // Show address list
                if (viewData.Items.Count > 0)
                    SetRightGrid(RightFunction.EditTable);
                else
                    SetRightGrid(RightFunction.Empty);
            }
        }

        private void FillAddressList(int functionNodeId)
        {
            // To set the right window
            viewData.Items.Clear();
            foreach (IAddressNode addressLine in _mainTrainer.GetAddressList())
            {
                if (addressLine.ParentIndex != functionNodeId)
                    continue;

                viewData.Items.Add(new ListViewItem(
                    new string[]
                    {
                        addressLine.Caption,    // Caption
                        "",                     // Original value
                        ""                      // Modified value
                    }));
                viewData.Items[viewData.Items.Count - 1].Tag = addressLine;
            }

            // To get memory content
            using (WindowsApi.ProcessMemory mem = new WindowsApi.ProcessMemory(_currentGameContext.ProcessId))
            {
                foreach (ListViewItem currentItem in viewData.Items)
                {
                    IAddressNode addressLine = currentItem.Tag as IAddressNode;
                    if (addressLine == null)
                        continue;

                    Object itemValue;
                    switch (addressLine.ValueType)
                    {
                        case AddressListValueType.Integer:
                            itemValue = mem.ReadInt32((IntPtr)addressLine.Address)
                                / addressLine.ValueScale;
                            break;
                        case AddressListValueType.Float:
                            itemValue = mem.ReadFloat((IntPtr)addressLine.Address)
                                / addressLine.ValueScale;
                            break;
                        case AddressListValueType.Char4:
                            itemValue = mem.ReadChar4((IntPtr)addressLine.Address);
                            break;
                        default:
                            itemValue = "";
                            break;
                    }
                    currentItem.SubItems[1].Text = itemValue.ToString();
                }
            }
        }

        public void ApplyModify(string keyCode = "")
        {
            if (!string.IsNullOrEmpty(keyCode) && "F6" != keyCode && "F5" != keyCode && UserModifyKeyCode != keyCode && ResourceModifyKeyCode != keyCode)
            {
                richLog.AppendText($"检测到按下 {keyCode} {Environment.NewLine}");
                return;
            }

            richLog.Clear();

            using (var mem = new WindowsApi.ProcessMemory(_currentGameContext.ProcessId))
            {
                if ("F5".Equals(keyCode))
                {
                    MoveXy(mem, keyCode);
                    return;
                }
                if ("F6".Equals(keyCode))
                {
                    try
                    {
                        // 将选中的对象共享出去
                        GetAllObject("4", true);
                    }
                    catch (BadProcessIdException)
                    {
                    }
                    return;
                }
                if (keyCode == UserModifyKeyCode || keyCode == ResourceModifyKeyCode)
                {
                    if (UserModifyKeyCode == keyCode)
                        HandleUnitModification(mem, keyCode);
                    if (ResourceModifyKeyCode == keyCode)
                        HandleResourceModification(mem, keyCode);
                }
                else
                {
                    ProcessViewData(mem, keyCode);
                }
            }
        }

        private void MoveXy(ProcessMemory mem, String keyCode)
        {
            try
            {
                // 将选中的对象共享出去
                GetAllObject("4", true);
            }
            catch (BadProcessIdException)
            {
                return;
            }

            foreach (var node in _mainTrainer.GetAddressList())
            {
                if (node.ParentIndex <= 3)
                    continue;

                string caption = node.Caption;
                int parentIndex = node.ParentIndex;
                uint addressValue = mem.ReadUInt32((IntPtr)(long)node.Address);
                string message = "";

                if (caption.Contains("坐标 - X"))
                {
                    float newVal = float.Parse(txtX.Text);
                    message = $"UPDATE|{caption}|{newVal}|{parentIndex}";
                }
                else if (caption.Contains("坐标 - Y"))
                {
                    float newVal = float.Parse(txtY.Text);
                    message = $"UPDATE|{caption}|{newVal}|{parentIndex}";
                }

                BroadcastUpdateByNode(message, keyCode);
            }

        }

        private void ProcessViewData(ProcessMemory mem, String keyCode = "")
        {
            foreach (ListViewItem item in viewData.Items)
            {
                string valueStr = item.SubItems[2].Text;
                if (string.IsNullOrEmpty(valueStr))
                    continue;

                var addressNode = item.Tag as IAddressNode;
                if (addressNode == null)
                    continue;

                string message = null;
                switch (addressNode.ValueType)
                {
                    case AddressListValueType.Integer:
                        if (Int32.TryParse(valueStr, out int intVal))
                        {
                            intVal = unchecked(intVal * addressNode.ValueScale);
                            message = $"UPDATE|{addressNode.Caption}|{intVal}|{addressNode.ParentIndex}";
                        }
                        break;
                    case AddressListValueType.Float:
                        if (float.TryParse(valueStr, out float floatVal))
                        {
                            floatVal = unchecked(floatVal * addressNode.ValueScale);
                            message = $"UPDATE|{addressNode.Caption}|{floatVal}|{addressNode.ParentIndex}";
                        }
                        break;
                    case AddressListValueType.Char4:
                        message = $"UPDATE|{addressNode.Caption}|{valueStr}|{addressNode.ParentIndex}";
                        break;
                }

                // 重置界面
                item.SubItems[2].Text = "";
                BroadcastUpdateByNode(message, keyCode);
            }
        }

        private void HandleResourceModification(ProcessMemory mem, String keyCode = "")
        {
            foreach (var node in _mainTrainer.GetAddressList())
            {
                if (node.ParentIndex != 2) continue;

                foreach (var user in selectUser.Text.Trim().Split(','))
                {
                    if (!node.Caption.Contains($"P{user} -")) continue;

                    string caption = node.Caption;
                    int parentIndex = node.ParentIndex;
                    string valueStr = "";

                    if (node.Caption.Contains("金"))
                    {
                        int newVal = int.Parse(txtCoin.Text);
                        valueStr = newVal.ToString();
                    }
                    else if (node.Caption.Contains("木"))
                    {
                        int newVal = int.Parse(txtWood.Text);
                        valueStr = newVal.ToString();
                    }
                    else if (node.Caption.Contains("最大人口"))
                    {
                        int newVal = int.Parse(txtHuman.Text);
                        valueStr = newVal.ToString();
                    }
                    else if (node.Caption.Contains("当前人口"))
                    {
                        valueStr = txtHumanMin.Text; // 根据实际情况调整
                    }

                    if (!string.IsNullOrEmpty(valueStr))
                    {
                        string msg = $"UPDATE|{node.Caption}|{valueStr}|{parentIndex}";
                        BroadcastUpdateByNode(msg, keyCode);
                    }
                }
            }
        }

        private void HandleUnitModification(ProcessMemory mem, String keyCode = "")
        {
            
            try
            {
                // 将选中的对象共享出去
                GetAllObject("4", true);
            }
            catch (BadProcessIdException)
            {
                return;
            }
            if (selected == null)
            {
                richLog.AppendText($"未发现选中目标! {Environment.NewLine}");
                return;
            }
            // 为了防止掉线 校验局域网所有客户端共享数据是否一致 如果不一致则不修改
            String notFoundDevice = "";
            String name = selected.Text?.Split(':')[1];
            bool allEq = _networkManager.ExistAllShareClient(name, ref notFoundDevice);
            if (!allEq)
            {
                richLog.AppendText($"设备{notFoundDevice}共享数据{name}不存在! {Environment.NewLine}");
                return;
            }

            foreach (var node in _mainTrainer.GetAddressList())
            {
                if (node.ParentIndex <= 3)
                    continue;

                string caption = node.Caption;
                int parentIndex = node.ParentIndex;
                uint addressValue = mem.ReadUInt32((IntPtr)(long)node.Address);
                string message = "";

                if (caption.Contains("力量"))
                {
                    int delta = int.Parse(txtLl.Text);
                    int newVal = (int)addressValue + delta;
                    message = $"UPDATE|{caption}|{newVal}|{parentIndex}";
                }
                else if (caption.Contains("敏捷"))
                {
                    int delta = int.Parse(txtMj.Text);
                    int newVal = (int)addressValue + delta;
                    message = $"UPDATE|{caption}|{newVal}|{parentIndex}";
                }
                else if (caption.Contains("智力"))
                {
                    int delta = int.Parse(txtZl.Text);
                    int newVal = (int)addressValue + delta;
                    message = $"UPDATE|{caption}|{newVal}|{parentIndex}";
                }
                else if (caption.Contains("经验值"))
                {
                    int delta = int.Parse(txtJy.Text);
                    int newVal = (int)addressValue + delta;
                    message = $"UPDATE|{caption}|{newVal}|{parentIndex}";
                }
                else if (caption.Contains("攻击1 - 基础1"))
                {
                    int delta = int.Parse(txtGj.Text);
                    int newVal = (int)addressValue + delta;
                    message = $"UPDATE|{caption}|{newVal}|{parentIndex}";
                }
                else if (caption.Contains("移动速度"))
                {
                    int delta = int.Parse(txtSpeed.Text);
                    int newVal = (int)addressValue + delta;
                    message = $"UPDATE|{caption}|{newVal}|{parentIndex}";
                }
                else if (caption.Contains("盔甲 - 数量"))
                {
                    int newVal = int.Parse(txtDefense.Text);
                    message = $"UPDATE|{caption}|{newVal}|{parentIndex}";
                }
                else if (caption.Contains("HP - 最大") || caption.Contains("HP - 目前"))
                {
                    int newVal = int.Parse(txtHp.Text);
                    message = $"UPDATE|{caption}|{newVal}|{parentIndex}";
                }
                else if (caption.Contains("MP - 最大") || caption.Contains("MP - 目前"))
                {
                    int newVal = int.Parse(txtMp.Text);
                    message = $"UPDATE|{caption}|{newVal}|{parentIndex}";
                }

                BroadcastUpdateByNode(message, keyCode);
            }
        }
        private void BroadcastUpdateByNode(String message, String keyCode = "")
        {
            if (!string.IsNullOrEmpty(message))
            {
                message += $"|";
                if (null != selected)
                {
                    String addressHex = selected.Text;
                    message += addressHex;
                }
                message += $"|";
                if (!String.IsNullOrEmpty(keyCode))
                {
                    message += keyCode;
                }
                _networkManager.BroadcastUpdate(message);
            }
        }

        private void WriteValue(ProcessMemory mem, IAddressNode node, string valueStr, out string message)
        {
            WriteValue(mem, node, null, valueStr, out message);
        }

        // 这个方法用来统一写值
        private void WriteValue(ProcessMemory mem, IAddressNode node, NewAddressListEventArgs eventNode, string valueStr, out string message)
        {
            message = "";
            if (string.IsNullOrEmpty(valueStr))
                return;
            if (null != node)
            {
                switch (node.ValueType)
                {
                    case AddressListValueType.Integer:
                        if (Int32.TryParse(valueStr, out int intVal))
                        {
                            intVal = unchecked(intVal * node.ValueScale);
                            mem.WriteInt32((IntPtr)node.Address, intVal);
                            message = $"UPDATE|{node.Caption}|{intVal}|{node.ParentIndex}";
                        }
                        break;
                    case AddressListValueType.Float:
                        if (float.TryParse(valueStr, out float floatVal))
                        {
                            floatVal = unchecked(floatVal * node.ValueScale);
                            mem.WriteFloat((IntPtr)node.Address, floatVal);
                            message = $"UPDATE|{node.Caption}|{floatVal}|{node.ParentIndex}";
                        }
                        break;
                    case AddressListValueType.Char4:
                        mem.WriteChar4((IntPtr)node.Address, valueStr);
                        message = $"UPDATE|{node.Caption}|{valueStr}|{node.ParentIndex}";
                        break;
                }
            }
            if (null != eventNode)
            {
                switch (eventNode.ValueType)
                {
                    case AddressListValueType.Integer:
                        if (Int32.TryParse(valueStr, out int intVal))
                        {
                            intVal = unchecked(intVal * eventNode.ValueScale);
                            mem.WriteInt32((IntPtr)eventNode.Address, intVal);
                            message = $"UPDATE|{eventNode.Caption}|{intVal}|{eventNode.ParentNodeIndex}";
                        }
                        break;
                    case AddressListValueType.Float:
                        if (float.TryParse(valueStr, out float floatVal))
                        {
                            floatVal = unchecked(floatVal * eventNode.ValueScale);
                            mem.WriteFloat((IntPtr)eventNode.Address, floatVal);
                            message = $"UPDATE|{eventNode.Caption}|{floatVal}|{eventNode.ParentNodeIndex}";
                        }
                        break;
                    case AddressListValueType.Char4:
                        mem.WriteChar4((IntPtr)eventNode.Address, valueStr);
                        message = $"UPDATE|{eventNode.Caption}|{valueStr}|{eventNode.ParentNodeIndex}";
                        break;
                }
            }
        }


        // 处理网络消息
        public void ApplyNetworkUpdate(string updateMessage)
        {
            DateTime now = DateTime.Now;
            lock (_lockObj)
            {
                if (_lastUpdateTimes.TryGetValue(updateMessage, out DateTime lastTime))
                {
                    if ((now - lastTime).TotalSeconds < 1)
                    {
                        Console.WriteLine($"在1秒内多次收到相同消息，忽略: {updateMessage}");
                        return;
                    }
                }
                _lastUpdateTimes[updateMessage] = now;
            }

            var parts = updateMessage.Split('|');
            if (parts.Length < 6 || parts[0] != "UPDATE")
                return;

            string itemText = parts[1];
            string valueStr = parts[2];
            int nodeIndex = int.TryParse(parts[3], out int idx) ? idx : 0;
            string hexString = parts[4];
            string keyCode = parts[5];
            // 如果不是修改选中角色
            if ("F3" == keyCode || "F6" == keyCode)
            {
                FindGame();
                richLog.AppendText($"{_networkManager.GetLocalIPAddress()} 触发查找游戏 {Environment.NewLine}");
            }

            using (var mem = new WindowsApi.ProcessMemory(_currentGameContext.ProcessId))
            {
                if (!String.IsNullOrEmpty(hexString) && (UserModifyKeyCode == keyCode || "F5" == keyCode))
                {
                    String name = hexString?.Split(':')[1]?.Trim();
                    List<String> realHexStrings = _networkManager.GetUnitAddressesByNameWithFilter(name);
                    if (realHexStrings.Count == 0)
                    {
                        richLog.AppendText($"{_networkManager.GetLocalIPAddress()} 没有找到该单位的地址 {hexString} {Environment.NewLine}");
                        return;
                    }
                    foreach (var unitAddressHex in realHexStrings)
                    {
                        String hexString2 = unitAddressHex.Replace("0x", "");
                        var unitAddress = Convert.ToUInt32(hexString2, 16);
                        List<NewAddressListEventArgs> addressListEventArgs = selectedAllNode.ExtractUnitAddresses(_currentGameContext, mem, unitAddressHex, name)[name];
                        foreach (var node in addressListEventArgs)
                        {
                            if (node.Caption.Equals(itemText))
                            {
                                WriteValue(mem, null, node, valueStr, out string msg);
                                richLog.AppendText($"人物[{node.Caption}]{hexString}->{valueStr} {Environment.NewLine}");
                            }
                        }
                    }
                }

                if (ResourceModifyKeyCode == keyCode || String.IsNullOrEmpty(keyCode))
                {
                    var nodeList = _mainTrainer.GetAddressList();
                    String nodeJson = JsonConvert.SerializeObject(nodeList);
                    foreach (var node in nodeList)
                    {
                        if (node.Caption.Equals(itemText))
                        {
                            WriteValue(mem, node, valueStr, out string msg);
                            if (!string.IsNullOrEmpty(msg))
                            {
                                richLog.AppendText($"资源[{node.Caption}]->{valueStr} {Environment.NewLine}");
                            }
                        }
                    }
                }
            }
        }

        // 在窗体关闭时清理网络资源
        protected override void OnFormClosing(FormClosingEventArgs e)
        {
            base.OnFormClosing(e);
            _networkManager?.Dispose();
        }

        /************************************************************************/
        /* Exception UI                                                         */
        /************************************************************************/
        private void ReportEnterDebugFailure()
        {
            labGameScanState.Text = "请以管理员身份运行";
        }

        private void ReportNoGameFoundFailure()
        {
            labGameScanState.Text = "游戏未运行，运行游戏后单击“查找游戏”";
        }

        private void ReportUnknownFailure(string message)
        {
            labGameScanState.Text = "发生未知错误：" + message;
        }

        private void ReportProcessIdFailure(int processId)
        {
            labGameScanState.Text = "错误的进程ID："
                + processId.ToString();
        }

        private void ReportVersionFailure(int processId, string version)
        {
            labGameScanState.Text = "检测到游戏，但版本（"
                + version
                + "）不被支持";
        }

        private void ReportVersionOk(int processId, string version)
        {
            labGameScanState.Text = "检测到游戏（"
                + processId.ToString()
                + "），游戏版本："
                + version
                + "（支持）";
        }

        /************************************************************************/
        /* GUI                                                                  */
        /************************************************************************/
        private void MenuHelpAbout_Click(object sender, EventArgs e)
        {
            MessageBox.Show("魔兽争霸3 冰封王座 内存修改器" + System.Environment.NewLine
                + Application.ProductVersion + System.Environment.NewLine
                + System.Environment.NewLine
                + "源代码在这里：https://github.com/tctianchi/War3Trainer" + System.Environment.NewLine
                + "学着自己动手改。" + System.Environment.NewLine
                + "局域网自动同步版本@midonggua修改。" + System.Environment.NewLine
                + "",
                "War3Trainer",
                MessageBoxButtons.OK,
                MessageBoxIcon.Information);
        }

        private void MenuFileExit_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void cmdGetAllObjects_Click(object sender, EventArgs e)
        {
            try
            {
                GetAllObject();
            }
            catch (WindowsApi.BadProcessIdException ex)
            {
                ReportProcessIdFailure(ex.ProcessId);
            }
        }

        private void cmdScanGame_Click(object sender, EventArgs e)
        {
            FindGame();
        }

        private void cmdModify_Click(object sender, EventArgs e)
        {
            try
            {
                ApplyModify();

                // Refresh left
                TreeNode selectedNode = viewFunctions.SelectedNode;
                if (selectedNode == null)
                    return;

                ITrainerNode functionNode = selectedNode.Tag as ITrainerNode;
                if (functionNode != null)
                    RefreshSelectedObject(functionNode);

                // Refresh right
                SelectFunction(selectedNode);
            }
            catch (WindowsApi.BadProcessIdException ex)
            {
                ReportProcessIdFailure(ex.ProcessId);
            }
        }

        private void viewFunctions_BeforeSelect(object sender, TreeViewCancelEventArgs e)
        {
            // Check whether modification is not saved
            bool isSaved = true;
            foreach (ListViewItem currentItem in viewData.Items)
            {
                if (!String.IsNullOrEmpty(currentItem.SubItems[2].Text))
                {
                    isSaved = false;
                    break;
                }
            }

            // Save all if not saved
            if (!isSaved)
            {
                cmdModify_Click(this, null);
            }

            // Select another function
            try
            {
                SelectFunction(e.Node);
            }
            catch (WindowsApi.BadProcessIdException ex)
            {
                ReportProcessIdFailure(ex.ProcessId);
            }
        }

        private enum RightFunction
        {
            Empty,
            Introduction,
            EditTable,
        }

        private void SetRightGrid(RightFunction function)
        {
            this.splitMain.Panel2.SuspendLayout();
            this.viewData.SuspendLayout();

            txtIntroduction.Visible = function == RightFunction.Introduction;
            viewData.Visible = function == RightFunction.EditTable;
            lblEmpty.Visible = function == RightFunction.Empty;

            txtIntroduction.Dock = DockStyle.Fill;
            viewData.Dock = DockStyle.Fill;
            lblEmpty.Location = new Point(0, 0);

            this.viewData.ResumeLayout(false);
            this.splitMain.Panel2.ResumeLayout(false);
            this.splitMain.Panel2.PerformLayout();
        }

        //////////////////////////////////////////////////////////////////////////       
        // Make the ListView editable
        private void ReplaceInputTextbox()
        {
            if (viewData.SelectedItems.Count < 1)
                return;
            ListViewItem currentItem = viewData.SelectedItems[0];

            txtInput.Location = new Point(
                viewData.Columns[0].Width + viewData.Columns[1].Width,
                currentItem.Position.Y - 2);
            txtInput.Width = viewData.Columns[2].Width;
        }

        private void viewData_KeyPress(object sender, KeyPressEventArgs e)
        {
            switch ((Keys)e.KeyChar)
            {
                case Keys.Enter:
                    viewData_MouseUp(sender, null);
                    e.Handled = true;
                    break;
            }
        }

        private void viewData_MouseUp(object sender, MouseEventArgs e)
        {
            // Get item
            if (viewData.SelectedItems.Count < 1)
                return;
            ListViewItem currentItem = viewData.SelectedItems[0];

            // Determine the content of edit box
            ReplaceInputTextbox();

            txtInput.Tag = currentItem;

            int textToEdit;
            if (String.IsNullOrEmpty(currentItem.SubItems[2].Text))
                textToEdit = 1;
            else
                textToEdit = 2;
            txtInput.Text = currentItem.SubItems[textToEdit].Text;

            // Enable editing
            txtInput.Visible = true;
            txtInput.Focus();
            txtInput.Select(0, 0);  // Cancel select all
        }

        private void viewData_ColumnWidthChanging(object sender, ColumnWidthChangingEventArgs e)
        {
            ReplaceInputTextbox();
        }

        private void viewData_Scrolling(object sender, EventArgs e)
        {
            viewData.Focus();
        }

        private void txtInput_Leave(object sender, EventArgs e)
        {
            txtInput.Visible = false;
            ListViewItem currentItem = txtInput.Tag as ListViewItem;
            if (currentItem == null)
                return;

            if (currentItem.SubItems[1].Text != txtInput.Text)
                currentItem.SubItems[2].Text = txtInput.Text;
            else
                currentItem.SubItems[2].Text = "";
        }

        private void txtInput_KeyDown(object sender, KeyEventArgs e)
        {
            switch (e.KeyCode)
            {
                case Keys.Enter:
                    CommitEditAndMoveNext(sender, 1);
                    e.Handled = true;
                    break;
                case Keys.Up:
                    CommitEditAndMoveNext(sender, -1);
                    e.Handled = true;
                    break;
                case Keys.Down:
                    CommitEditAndMoveNext(sender, 1);
                    e.Handled = true;
                    break;
                case Keys.Escape:
                    DiscardEdit(sender);
                    e.Handled = true;
                    break;
            }
        }

        private void DiscardEdit(object editBox)
        {
            // Roll back content of the edit box
            viewData_MouseUp(editBox, null);

            // Hide edit box
            txtInput_Leave(editBox, null);

            // Restore focus
            viewData.Focus();
        }

        private void CommitEditAndMoveNext(object editBox, int delta)
        {
            // Commit
            txtInput_Leave(editBox, null);

            // Move to another line
            viewData.Focus();
            if (viewData.SelectedItems.Count > 0)
            {
                int nextIndex = viewData.SelectedItems[0].Index + delta;
                if (nextIndex < viewData.Items.Count &&
                    nextIndex >= 0)
                {
                    viewData.Items[nextIndex].Selected = true;
                    viewData.Items[nextIndex].Focused = true;
                    viewData.Items[nextIndex].EnsureVisible();
                }
                viewData_MouseUp(editBox, null);
            }
        }

        /************************************************************************/
        /* Debug                                                                */
        /************************************************************************/
        private void menuDebug1_Click(object sender, EventArgs e)
        {
            string strIndex = Microsoft.VisualBasic.Interaction.InputBox(
                "nIndex = 0x?",
                "War3Common.ReadFromGameMemory(nIndex)",
                "0", -1, -1);
            if (String.IsNullOrEmpty(strIndex))
                return;

            Int32 nIndex;
            if (!Int32.TryParse(
                strIndex,
                System.Globalization.NumberStyles.HexNumber,
                System.Globalization.NumberFormatInfo.InvariantInfo,
                out nIndex))
            {
                nIndex = 0;
            }

            try
            {
                UInt32 result = 0;
                using (WindowsApi.ProcessMemory mem = new WindowsApi.ProcessMemory(_currentGameContext.ProcessId))
                {
                    NewChildrenEventArgs args = new NewChildrenEventArgs();
                    War3Common.GetGameMemory(
                        _currentGameContext, ref args);
                    result = War3Common.ReadFromGameMemory(
                        mem, _currentGameContext, args,
                        nIndex);
                }
                MessageBox.Show(
                    "0x" + result.ToString("X"),
                    "War3Common.ReadFromGameMemory(0x" + strIndex + ")");
            }
            catch (WindowsApi.BadProcessIdException ex)
            {
                ReportProcessIdFailure(ex.ProcessId);
            }
        }

        private void ToolStripMenuItemClients_Click(object sender, EventArgs e)
        {
            //// 将客户端信息连接成一个字符串，以换行符分隔
            //string message = string.Join(Environment.NewLine, _networkManager._otherMachines);
            //// 弹出 MessageBox 显示信息
            //MessageBox.Show(message, "客户端信息", MessageBoxButtons.OK, MessageBoxIcon.Information);
            OverlayForm menuForm = new OverlayForm();
            menuForm.Show();
        }

        private void btnEnableKeyListener_Click(object sender, EventArgs e)
        {
            if (this._currentGameContext == null)
            {
                richLog.AppendText($"游戏未启动 {Environment.NewLine}");
            }
            else
            {
                // 释放旧的钩子实例
                if (this.hook != null)
                {
                    this.hook.OnKeyDownEvent -= this.hook_OnKeyDownEvent;
                    this.hook.Stop();
                    this.hook = null;
                }

                this.btnEnableKeyListener.Enabled = false;
                this.btnEnableKeyListener.Text = "已生效";
                this.hook = new KeyboardHook();
                this.hook.OnKeyDownEvent += this.hook_OnKeyDownEvent;
            }
        }

        private void hook_OnKeyDownEvent(object sender, KeyEventArgs e)
        {
            if ("F4".Equals(e.KeyCode.ToString()))
            {
                this.hook.OnKeyDownEvent -= this.hook_OnKeyDownEvent;
                this.hook.Stop();
                this.hook = null;
                this.btnEnableKeyListener.Enabled = true;
                this.btnEnableKeyListener.Text = "启用监听";
            }
            else
            {
                this.ApplyModify(e.KeyCode.ToString());
            }
        }

        private void btnZero_Click(object sender, EventArgs e)
        {
            txtGj.Text = "0";
            txtMj.Text = "0";
            txtZl.Text = "0";
            txtLl.Text = "0";
            txtJy.Text = "0";
        }

        private void button1_Click(object sender, EventArgs e)
        {
            txtGj.Text = "500";
            txtMj.Text = "500";
            txtZl.Text = "500";
            txtLl.Text = "500";
            txtJy.Text = "500";
        }

        private void button2_Click(object sender, EventArgs e)
        {
            txtGj.Text = "10000";
            txtMj.Text = "10000";
            txtZl.Text = "10000";
            txtLl.Text = "10000";
            txtJy.Text = "10000";
        }

        private void button3_Click(object sender, EventArgs e)
        {
            txtX.Text = "41.99214";
            txtY.Text = "16.16162";
        }

        private void button4_Click(object sender, EventArgs e)
        {

            txtX.Text = "478.7308";
            txtY.Text = "419.8312";
        }

        private void button5_Click(object sender, EventArgs e)
        {
            txtX.Text = "66.94981";
            txtY.Text = "268.79";
        }

        private void button6_Click(object sender, EventArgs e)
        {
            txtX.Text = "201.94981";
            txtY.Text = "187.79";
        }

        private void button7_Click(object sender, EventArgs e)
        {
            txtX.Text = "316.94981";
            txtY.Text = "29.79";
        }

        private void button10_Click(object sender, EventArgs e)
        {
            txtX.Text = "146.94981";
            txtY.Text = "455.79";
        }

        private void button9_Click(object sender, EventArgs e)
        {
            txtX.Text = "252.94981";
            txtY.Text = "284";
        }

        private void button8_Click(object sender, EventArgs e)
        {
            txtX.Text = "446";
            txtY.Text = "236";
        }

        private void btnReset_Click(object sender, EventArgs e)
        {
            FindGame();
            _networkManager.SHARE_DATA.Clear();
            _networkManager.SendBroadcastsClearShareData();
        }

        private void selectUser_Leave(object sender, EventArgs e)
        {
            // 1. 替换中文逗号为英文逗号
            string text = selectUser.Text.Replace('，', ',');

            // 2. 移除多余的逗号，避免连续逗号
            // 例：将连续的逗号替换为单个
            while (text.Contains(",,"))
            {
                text = text.Replace(",,", ",");
            }

            // 3. 去除开头和结尾的逗号
            text = text.Trim(',');

            // 4. 保持只包含数字和逗号
            //（可选，增强过滤）
            var allowedChars = "0123456789,";
            var filteredChars = new string(text.Where(c => allowedChars.Contains(c)).ToArray());

            // 5. 更新文本
            if (selectUser.Text != filteredChars)
            {
                int selStart = selectUser.SelectionStart;
                selectUser.Text = filteredChars;
                selectUser.SelectionStart = Math.Min(selStart, selectUser.Text.Length);
            }
        }

        private void button11_Click(object sender, EventArgs e)
        {
            txtGj.Text = "100000";
            txtMj.Text = "100000";
            txtZl.Text = "100000";
            txtLl.Text = "100000";
            txtJy.Text = "100000";
        }
    }

}
